#include "EApp.h"
#include "EGame.h"
#include "eCPP.h"

namespace engine {

//------------------------------------------------------------
const string EApp::s_sOgreCfgFileName           = "ogre.cfg";
const string EApp::s_sOgreLogFileName           = "Ogre.log";
const string EApp::s_sOgreResourcesCfgFileName  = "resources.cfg";
#ifdef _DEBUG
  const string EApp::s_sOgrePluginsCfgFileName    = "plugins_d.cfg";
#else
  const string EApp::s_sOgrePluginsCfgFileName    = "plugins.cfg";
#endif
//------------------------------------------------------------
EApp::EApp()
{ 
  m_pFrameListener  = NULL;
  m_pRoot           = NULL;
// Provide a nice cross platform solution for locating the configuration files
// On windows files are searched for in the current working directory, on OS X however
// you must provide the full path, the helper function macBundlePath does this for us.
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
  m_pResourcePath = macBundlePath() + "/Contents/Resources/";
#else
  m_pResourcePath = "";
#endif
}

//------------------------------------------------------------
EApp::~EApp()
{
  delete m_pFrameListener;
  delete m_pRoot;
}

//------------------------------------------------------------
bool EApp::go(void)
{
    cTEST( setup() );

    m_pRoot->startRendering();

    // clean up
    destroyScene();

    return true;
}

//------------------------------------------------------------
bool EApp::setup(void)
{

  String pluginsPath;
  // only use plugins.cfg if not static
#ifndef OGRE_STATIC_LIB
  pluginsPath = m_pResourcePath + s_sOgrePluginsCfgFileName;
#endif

  m_pRoot = new Root(pluginsPath,
      m_pResourcePath + s_sOgreCfgFileName, m_pResourcePath + s_sOgreLogFileName);

  setupResources();

  bool carryOn = configure();
  if (!carryOn) return false;

  chooseSceneManager();
  createCamera();
  createViewports();

  // Set default mipmap level (NB some APIs ignore this)
  TextureManager::getSingleton().setDefaultNumMipmaps(5);

  // Create any resource listeners (for loading screens)
  createResourceListener();
  // Load resources
  loadResources();

  // Create the scene
  cTEST( createScene() );

  createFrameListener();

  return true;
}

//------------------------------------------------------------
bool EApp::configure(void)
{
  // Show the configuration dialog and initialise the system
  // You can skip this and use root.restoreConfig() to load configuration
  // settings if you were sure there are valid ones saved in ogre.cfg
  //if( m_pRoot->showConfigDialog() )
  if( m_pRoot->restoreConfig() )
  {
    // If returned true, user clicked OK so initialise
    // Here we choose to let the system create a default rendering window by passing 'true'
    mWindow = m_pRoot->initialise(true);
    return true;
  }
  else
  {
    return false;
  }
}

//------------------------------------------------------------
void EApp::chooseSceneManager(void)
{
  // Create the SceneManager, in this case a generic one
  m_pSceneManager = m_pRoot->createSceneManager(ST_GENERIC, "MAIN_SCREEN");
  cASSERT( m_pSceneManager != NULL );
  g_pGame->m_sceneManager.setOgreSceneManager( *m_pSceneManager );
}

//------------------------------------------------------------
void EApp::createCamera(void)
{
  m_pCamera = m_pSceneManager->createCamera("PlayerCam");

  /*m_pCamera->setOrientation( Quaternion(0.950208f, -0.064778f, -0.30407f, -0.020729f ) );
  m_pCamera->setPosition(Vector3(-7.6496f, 13.9775f, -4.06736f));*/
  m_pCamera->setOrientation( Quaternion(0.950208f, -0.064778f, -0.30407f, -0.020729f ));
  m_pCamera->setPosition(Vector3(-28.26f, 55.186f, 49.4751f));
  // Look back along -Z
  //m_pCamera->lookAt(Vector3(0,0,-3));
  
  
  m_pCamera->setNearClipDistance( 0.5f );
  //m_pCamera->setFarClipDistance(5000);
  /*m_pCamera->setProjectionType(ProjectionType::PT_ORTHOGRAPHIC);
  
  RenderSystem* pRenderSystem = m_pRoot->getRenderSystem();
  Matrix4   mProj;
  pRenderSystem->_makeOrthoMatrix(Degree(70.f),Real(800) / Real(600),-0.3f,0.3f,mProj);
  m_pCamera->setCustomProjectionMatrix(true, mProj);*/
}

//------------------------------------------------------------
void EApp::createFrameListener(void)
{
  m_pFrameListener= new EFrameListener(*this, mWindow, m_pCamera);
  //m_pFrameListener->showDebugOverlay(true);
  m_pRoot->addFrameListener(m_pFrameListener);
}

//------------------------------------------------------------
void EApp::createViewports(void)
{
  // Create one viewport, entire window
  Viewport* pVp = mWindow->addViewport(m_pCamera);
  pVp->setBackgroundColour(ColourValue(0,0,0));

  // Alter the camera aspect ratio to match the viewport
  Degree degFov( 80.f );
  m_pCamera->setFOVy( degFov );
  m_pCamera->setAspectRatio(
      Real(pVp->getActualWidth()) / Real(pVp->getActualHeight()));
}

//------------------------------------------------------------
void EApp::setupResources(void)
{
  // Load resource paths from config file
  ConfigFile cf;
  cf.load(m_pResourcePath + s_sOgreResourcesCfgFileName);

  // Go through all sections & settings in the file
  ConfigFile::SectionIterator seci = cf.getSectionIterator();

  String secName, typeName, archName;
  while (seci.hasMoreElements())
  {
    secName = seci.peekNextKey();
    ConfigFile::SettingsMultiMap *settings = seci.getNext();
    ConfigFile::SettingsMultiMap::iterator i;
    for (i = settings->begin(); i != settings->end(); ++i)
    {      typeName = i->first;
      archName = i->second;
#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE
      // OS X does not set the working directory relative to the app,
      // In order to make things portable on OS X we need to provide
      // the loading with it's own bundle path location
      ResourceGroupManager::getSingleton().addResourceLocation(
          String(macBundlePath() + "/" + archName), typeName, secName);
#else
      ResourceGroupManager::getSingleton().addResourceLocation(
          archName, typeName, secName);

#endif
    }
  }
}

//------------------------------------------------------------
void EApp::loadResources(void)
{
  // Initialise, parse scripts etc
  ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
}

} // end namespace
